Skip to content

[RUN-4595] ReImplement Functional Tests#428

Open
fdevans wants to merge 11 commits into
mainfrom
grails7-upgrade
Open

[RUN-4595] ReImplement Functional Tests#428
fdevans wants to merge 11 commits into
mainfrom
grails7-upgrade

Conversation

@fdevans

@fdevans fdevans commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Re-enables and modernizes the Testcontainers functional test suite so it runs on
every CI build and passes against Rundeck 6 (Grails 7). Previously these tests ran
only on main/tag builds and were incompatible with Rundeck 6's project-import and
REST API behavior, so they gave no coverage during day-to-day development.

What changed

CI/CD (.github/workflows/gradle.yml)

  • Functional tests now run on every push/PR (removed the main/tags-only guards on
    copyPluginArtifact and functionalTest).
  • functionalTest runs with --stacktrace --info, teeing the full Gradle transcript
    to two locations (ci-logs/ and functional-test/build/ci-reports/) to work around
    upload-artifact skipping dot-directories.
  • Always uploads test reports + logs as a build artifact.
  • .gitignore: ignore ci-logs/.

Rundeck 6 / Grails 7 compatibility (functional-test/)

  • Version single-sourcing: RUNDECK_TEST_IMAGE and the new RUNDECK_ARCHIVE_APP_VERSION
    are derived from rundeck-core in gradle/libs.versions.toml instead of hardcoded
    5.18.0 / 5.0.0.
  • Project archive fixes (TestUtil.createArchiveJarFile): stamp Rundeck-Application-Version
    from RUNDECK_ARCHIVE_APP_VERSION (default 6.0.0, since Rundeck 6 rejects 5.x-stamped
    archives); write explicit directory entries (trailing /, shallow-to-deep) before files so
    AsyncImportService no longer treats jobs/ as a zero-byte file ("Not a directory").
    Compatible with both Rundeck 5 and 6.
  • Project creation (createProjectGrails7IfMissing): Grails 7 POST /projects requires
    top-level name plus config["project.name"].
  • OkHttp 4 migration: corrected RequestBody.create(MediaType, body) argument order.
  • Node availability (waitForNodeAvailability): nudges resource providers via
    PUT project/{project}/config/time and polls up to 3 minutes (was a fixed 5×2s loop).

Diagnostics

  • importProjectArchiveFromTestResources parses ProjectImportStatus and, on failure,
    logs the pretty-printed status JSON and dumps (truncated) Rundeck container logs to stderr
    (RundeckCompose.appendRundeckContainerLogsToStdErr).
  • Verbose testLogging (failed/passed/skipped/stdout/stderr, full exceptions, stack traces).

Docs

  • functional-test/README.md: prerequisites bumped to Java 17 / Gradle 8.

Test plan

  • ./gradlew build
  • ./gradlew :functional-test:copyPluginArtifact :functional-test:functionalTest
    (Docker running) passes against the Rundeck image pinned by rundeck-core.
  • CI functional-test job green; artifact with logs/reports uploaded.

fdevans added 10 commits April 6, 2026 21:22
Rundeck 6's AsyncImportService expects explicit directory entries (with trailing /)
in project archives. Without them, directories like "jobs" extract as zero-byte files,
causing "Not a directory" errors during import.

Changes:
- Collect all parent directories from file paths
- Create JarEntry objects with trailing / for each directory
- Write directory entries before file entries, ordered shallow-to-deep
- Normalize paths to use forward slashes

This ensures archives are compatible with both Rundeck 5 and 6 import mechanisms.
@fdevans fdevans added this to the 6.0.0 milestone Apr 15, 2026
@fdevans

fdevans commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Jul 1, 2026

Copy link
Copy Markdown

@copilot resolve the merge conflicts in this pull request

Merge conflicts resolved in commit c3ff691. The only conflict was in gradle/libs.versions.toml where rundeck-core versions differed — kept the branch's 6.0.0-alpha1-20260407 version since this branch targets Rundeck 6.0.x development.

@fdevans fdevans requested a review from a team July 1, 2026 22:08
@fdevans fdevans modified the milestones: 6.0.0, 6.1.0 Jul 1, 2026
@fdevans fdevans added the to-jira label Jul 1, 2026
@fdevans fdevans marked this pull request as ready for review July 1, 2026 22:13
Copilot AI review requested due to automatic review settings July 1, 2026 22:13
@fdevans fdevans changed the title ReImplement Functional Tests [RUN-4595] ReImplement Functional Tests Jul 1, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the functional/integration test harness to align with Rundeck 6 / Grails 7 expectations (project creation/import semantics, archive format quirks) and improves CI visibility by capturing and uploading full Gradle/test logs.

Changes:

  • Switch functional tests to use a Rundeck 6.x-aligned version catalog entry and propagate it into the functional test configuration.
  • Rework project archive generation and project import/setup helpers for Rundeck 6 async import behavior and Grails 7 project creation requirements.
  • Improve CI diagnostics by tee’ing Gradle output to non-hidden directories and uploading logs/reports as artifacts.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
gradle/libs.versions.toml Pins the Rundeck core version used by the build/test setup.
functional-test/src/test/groovy/functional/util/TestUtil.groovy Adjusts project archive creation (manifest versioning + explicit directory entries).
functional-test/src/test/groovy/functional/MultiNodeAuthSpec.groovy Refactors setup to reuse new Grails 7 project creation/import helpers; updates OkHttp RequestBody usage.
functional-test/src/test/groovy/functional/base/RundeckCompose.groovy Adds helper to dump Rundeck container logs on failures.
functional-test/src/test/groovy/functional/base/BaseTestConfiguration.groovy Centralizes project creation/import + adds config-time “touch” for resource refresh and better import failure diagnostics.
functional-test/README.md Updates prerequisites to Java 17 / Gradle 8.
functional-test/build.gradle Wires Rundeck version into test system properties; enables verbose test logging.
.gitignore Ignores new ci-logs/ output directory.
.github/workflows/gradle.yml Always runs functional tests on push and uploads logs/reports as artifacts.

Comment on lines +198 to +208
def waitForNodeAvailability(String projectName, String nodeName) {
touchProjectConfigTime(projectName)
final long deadlineNanos = System.nanoTime() + TimeUnit.MINUTES.toNanos(3)
def result = client.apiCall { api -> api.listNodes(projectName, ".*") }

while (result.get(nodeName) == null && System.nanoTime() < deadlineNanos) {
touchProjectConfigTime(projectName)
sleep(3000)
result = client.apiCall { api -> api.listNodes(projectName, ".*") }
}
}
Comment on lines +48 to +52
def opt = getContainerByServiceName("rundeck")
if (!opt.isPresent()) {
System.err.println("${header}\n(no rundeck service container in compose state)")
return
}
Comment on lines +40 to +43
// Rundeck Docker image tag must match `rundeck-core` in ../gradle/libs.versions.toml (single source of truth).
systemProperty('RUNDECK_TEST_IMAGE', "rundeck/rundeck:${libs.versions.rundeck.core.get()}")
// Project archive manifest must match server generation; see TestUtil.createArchiveJarFile
systemProperty('RUNDECK_ARCHIVE_APP_VERSION', libs.versions.rundeck.core.get())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants